package org.bluedream.core.module.service.goods;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.commons.collections.map.HashedMap;
import org.bluedream.comm.utils.CreateGUIDUtil;
import org.bluedream.comm.utils.EmptyUtil;
import org.bluedream.comm.utils.RestResult;
import org.bluedream.comm.utils.excel.ExcelException;
import org.bluedream.comm.utils.excel.ExcelUtil;
import org.bluedream.core.module.base.OrgBaseServiceImpl;
import org.bluedream.core.module.dao.goods.GoodsDao;
import org.bluedream.core.module.entity.emp.Emp;
import org.bluedream.core.module.entity.goods.Goods;
import org.bluedream.core.module.entity.goods.Product;
import org.bluedream.core.utils.UserUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @ClassName depItemUserService
 * @Description TODO
 * @Author foxsand
 * @Data 2021-07-23 17:17
 * @Version
 */
@Service
@DS("master")
@Transactional(
        readOnly = true
)
public class GoodsService extends OrgBaseServiceImpl<GoodsDao, Goods> implements IService<Goods> {
    private static final Logger logger = LoggerFactory.getLogger(GoodsService.class);
    @Resource
    private ProductService productService;

    @Resource
    DataSourceTransactionManager dataSourceTransactionManager;

    @Override
    public Goods getById(Serializable id) {
        if (EmptyUtil.isEmpty(id)){
            return new Goods();
        }
        return super.getById(id);
    }

    public IPage<Goods> findPage(Goods entity, String... args) {
        Map<String , Object> search = new HashedMap();
        if (EmptyUtil.isNoEmpty(entity.getCode())
                || EmptyUtil.isNoEmpty(entity.getName())
                || EmptyUtil.isNoEmpty(entity.getBarcode())
                || EmptyUtil.isNoEmpty(entity.getClsCode())
        ){
            if (EmptyUtil.isNoEmpty(entity.getCode())){
                search.put("goods.code" , entity.getCode());
            }
            if (EmptyUtil.isNoEmpty(entity.getName())){
                search.put("goods.name" , entity.getName());
            }
            if (EmptyUtil.isNoEmpty(entity.getBarcode())){
                search.put("goods.barCode" , entity.getBarcode());
            }
            if (EmptyUtil.isNoEmpty(entity.getClsCode())){
                search.put("goods.cls_code;eq" , entity.getClsCode());
            }
        }
        return super.findPage(entity , true , search , args);
    }

    public RestResult getOne(Goods entity){
        QueryWrapper<Goods> qw = new QueryWrapper<>();
        if (EmptyUtil.isNoEmpty(entity.getCode())){
            qw.eq("goods.code" , entity.getCode());
        }else if (EmptyUtil.isNoEmpty(entity.getBarcode())){
            qw.eq("goods.barcode" , entity.getBarcode());
        }else {
            return RestResult.error("没有传入正确的商品代码，请确认！");
        }
        qw.eq("goods.org_code" , UserUtil.getLoginOrgCode());

        Goods goods = super.getOne(qw);
        if (EmptyUtil.isNoEmpty(goods)){
            return RestResult.ok(goods);
        }else {
            return RestResult.error("无此商品！");
        }
    }

    @Transactional(
            readOnly = false,
            rollbackFor = Exception.class
    )
    public RestResult saveEntity(Goods entity){
        try {
            if (entity.getIsNewRecord()){
                String id = CreateGUIDUtil.GenerateGUID();
                entity.setId(id);
            }
            if (EmptyUtil.isEmpty(entity.getProductList())){
                return RestResult.error("商品：" + entity.getName() + "缺少合法的条码，无法保存。");
            }

            for (Product p:entity.getProductList()
            ) {
                p.setId(entity.getId());
                if (EmptyUtil.isNoEmpty(entity.getOrgCode())){
                    p.setOrgCode(entity.getOrgCode());
                }
                RestResult restResult = productService.getOne(p);
                if (restResult.getStatus() != 0){
                    p.setIsNewRecord(true);
                }
            }
            Product p0 = entity.getProductList().get(0);
            entity.setBarcode(p0.getBarcode());
            entity.setSpec(p0.getSpec());
            entity.setUnit(p0.getUnit());
            entity.setQpc(p0.getQpc());
            entity.setQpcStr(p0.getQpcStr());
            entity.setOprice(p0.getOprice());
            super.save(entity);
            productService.saveBatch(entity.getProductList());
        }catch (Exception e1){
            e1.printStackTrace();
            logger.error(e1.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResult.error("数据保存失败:" + e1.getMessage());
        }
        return RestResult.ok(entity.getName() + "保存成功。");
    }

    /**
     * 手动开启事务提交，
     * @param file
     * @return
     */
    public RestResult excelImport(MultipartFile file){
        try {
            List<Goods> goodsList = ExcelUtil.import2List(file , 1 , Goods.class , 0);
            String msgStatus = "";
            for (Goods g:goodsList
                 ) {
                int checkStatus = getOne(g).getStatus();
                if (checkStatus != 0){
                    g.setCreateBy(UserUtil.getLoginInfo().getLoginCode());
                    g.setOrgCode(UserUtil.getLoginOrgCode());
                    msgStatus = baseMapper.excelImport(g);
                }
            }
            if (!"0".equals(msgStatus)){
                return RestResult.error();
            }
            return RestResult.ok();
        }catch (Exception e){
            e.printStackTrace();
            return RestResult.error(e.getMessage());
        }
    }

    /**
     * 商品条形码编码规则
     * 1.00-09代表美国，加拿大，45－49代表日本，690-693代表中国大陆，471代表我国台湾地区，489代表香港特区
     * 2.前12位中的奇数位数字相加得到A值
     * 3.前12为中的偶数位数字相加得到B值
     * 4.A+3*B得到的数字取个位数得到C值
     * 5.10-C=X X即为第13位的校验位
     * 6.条码长度：13位
     *
     * 需求：
     * 1.内部自编码
     * 2.条码前2位为商品品类编码表中的1级分类编码
     * 3.后10位按升序取最小值。
     * 4.新条码不能与已存在的条码重复
     * 5.第13位为校验位
     * 6.商品所属品类需要通过v_scode传入
     * @return
     */
    public String barcode(String startCode){
        QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("goods.cls_code" , startCode);
        List<String> barcodeList = productService.selectBarcode(queryWrapper);
        int tmpCode = 1;

        String tStr = "";
        if (EmptyUtil.isEmpty(barcodeList)){
            tStr = "001";
        }else {
            for (int i = 0; i < 999; i++) {
                String s1 = ("00" + tmpCode).substring(("00" + tmpCode).length() - 3);
                if (!barcodeList.contains(s1)){
                    tStr = s1;
                    break;
                }
                tmpCode++;
            }
        }
        if (tmpCode > 999){
            throw new RuntimeException("无可用条码了");
        }
        tStr = startCode + tStr;
        int a = 0, b = 0;
        for (int i = 1; i < tStr.length(); i++) {
            int index = Integer.parseInt(tStr.substring(i , i + 1));
            if (i % 2 != 0){
                a = a + index;
            }else {
                b = b + index;
            }
        }
        String checkBit = Integer.toString((a + 3*b));
        return tStr + (10 - Integer.parseInt(checkBit.substring(checkBit.length() -1)));
    }
}
